#!/usr/bin/env python
# _*_ coding: UTF-8 _*_

import os, sys, threading
from SSHBatch.Reactor import Reactor
from SSHBatch.Log import Log
from SSHBatch.Invoker import Invoker

try: import readline
except: pass

class KBAgent(threading.Thread):
    def __init__(self, ctx):
        threading.Thread.__init__(self)
        self.reactor = ctx["reactor"]
        self.logger = ctx["logger"]
        self.invoker = ctx["invoker"]
        self.config = ctx["config"]
        self.lock = ctx["lock"]
        self.rt = ctx["rt"]
        self.fd = sys.stdin.fileno()
        self.line = ""
    
    def open(self):
        """
        Running as I/O deplexing
        """
        self.reactor.register(self, Reactor.READ)

    def run(self):
        """
        Running as a standalone thread
        """
        if self.rt["has_readline"]:
            readline.parse_and_bind("tab: complete")
            readline.set_completer(self.invoker.completer)
            history = os.path.expanduser(self.config["Global"]["history"])
            if os.path.exists(history):
                try:
                    readline.read_history_file(history)
                except Exception, e:
                    self.logger.write("readline error %s\n" % str(e))
        shutdown = False
        while not shutdown and not self.reactor.stopped():
            try:
                line = raw_input(self.invoker.prompt(0, True))
                line = line + "\n"
            except KeyboardInterrupt, e:
                self.logger.write("keyboard interrupted %s\n" % str(e))
                line = ""
            except (Exception, SystemExit), e:
                self.logger.write("exception %s\n" % str(e))
                line = ""
            if not line:
                line = "quit"
                if self.rt["mode"] == Invoker.SSH:
                    line = "%s %s" % (self.config["sshbatchid"], line) 
            
            if self.lock: 
                self.lock.acquire()
            try:
                ret = self.invoker.dispatch(line)
            except (Exception, KeyboardInterrupt, SystemExit), e:
                self.logger.write("invoking exception %s\n" % str(e))
                self.reactor.stop()
                shtudown = True
                ret = Invoker.FAIL
                raise
            finally:
                if self.lock: 
                    self.lock.release()
            if ret == Invoker.QUIT:
                shutdown = True

        if self.rt["has_readline"]:
            try:
                readline.write_history_file(history)
            except Exception, e:
                self.logger.write("readline rror %s\n" % str(e))

    def fileno(self):
        return self.fd
    
    def handleRead(self):
        try:
            line = os.read(self.fd, 4096)
        except e:
            self.logger.log(Log.LGLEVEL_FATAL, "keyboard error")
            line = ""
        if not line:
            self.invoker.cmdQuit()
            return
        if line[-1] == '\n':
            ret = self.invoker.dispatch(self.line + line)
            self.line = ""
            if ret != Invoker.QUIT:
                self.invoker.prompt()
        else:
            self.line = self.line + line
            
    def handleWrite(self):
        assert 0, "BUG!!!"
    
    def handleExcept(self):
        assert 0, "BUG!!!"
